package com.zp.business.impl.infusion;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.business.entity.infusion.InfusionItem;
import com.zp.business.entity.infusion.InfusionRecord;
import com.zp.business.entity.infusion.bo.InfusionItemBo;
import com.zp.business.entity.infusion.bo.InfusionRecordBo;
import com.zp.business.entity.infusion.vo.InfusionItemVo;
import com.zp.business.entity.infusion.vo.InfusionRecordVo;
import com.zp.business.mapper.infusion.InfusionItemMapper;
import com.zp.business.mapper.infusion.InfusionRecordMapper;
import com.zp.business.service.infusion.IInfusionRecordService;
import com.zp.common.core.constant.CacheNames;
import com.zp.common.core.constant.UserConstants;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.redis.utils.CacheUtils;
import com.zp.system.api.entity.SysDictData;
import com.zp.system.api.entity.SysOrg;
import com.zp.system.api.entity.SysUser;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 输液室记录Service业务层处理
 *
 * @author zhang peng
 * @ date 2025-02-08
 */
@RequiredArgsConstructor
@Service
public class InfusionRecordServiceImpl implements IInfusionRecordService {

    static Map<String, SysOrg> sysOrgMap = CacheUtils.get(CacheNames.SYS_ORG);
    /**
     * 用户信息
     */
    static Map<String, SysUser> SYS_USER_MAP = CacheUtils.get(CacheNames.SYS_USER);
    /**
     * 库存消耗类型字典
     */
    static List<SysDictData> INFUSION_OPERATOR_TYPE_MAP = CacheUtils.get(CacheNames.SYS_DICT, CacheNames.INFUSION_OPERATOR_TYPE);
    private final InfusionRecordMapper baseMapper;
    private final InfusionItemMapper infusionItemMapper;

    /**
     * 查询输液室记录
     */
    @Override
    public InfusionRecordVo queryById(String infusionRecordId) {
        return baseMapper.selectVoById(infusionRecordId);
    }

    /**
     * 查询输液室记录列表(分页)
     */
    @Override
    public TableDataInfo<InfusionRecordVo> queryPageList(InfusionRecordBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<InfusionRecord> lqw = buildQueryWrapper(bo);
        Page<InfusionRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询输液室记录列表(不分页)
     */
    @Override
    public List<InfusionRecordVo> queryList(InfusionRecordBo bo) {
        LambdaQueryWrapper<InfusionRecord> lqw = buildQueryWrapper(bo);
        lqw.orderByAsc(InfusionRecord::getCreateTime);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<InfusionRecord> buildQueryWrapper(InfusionRecordBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<InfusionRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getItemId()), InfusionRecord::getItemId, bo.getItemId());
        lqw.eq(bo.getDistributionTime() != null, InfusionRecord::getDistributionTime, bo.getDistributionTime());
        lqw.eq(StringUtils.isNotBlank(bo.getDistributionNurse()), InfusionRecord::getDistributionNurse, bo.getDistributionNurse());
        lqw.eq(bo.getPunctureTime() != null, InfusionRecord::getPunctureTime, bo.getPunctureTime());
        lqw.eq(StringUtils.isNotBlank(bo.getPunctureNurse()), InfusionRecord::getPunctureNurse, bo.getPunctureNurse());
        lqw.eq(bo.getPullNeedleTime() != null, InfusionRecord::getPullNeedleTime, bo.getPullNeedleTime());
        lqw.eq(StringUtils.isNotBlank(bo.getPullNeedleNurse()), InfusionRecord::getPullNeedleNurse, bo.getPullNeedleNurse());
        lqw.eq(bo.getInfusionStartTime() != null, InfusionRecord::getInfusionStartTime, bo.getInfusionStartTime());
        lqw.eq(bo.getInfusionEndTime() != null, InfusionRecord::getInfusionEndTime, bo.getInfusionEndTime());
        lqw.eq(StringUtils.isNotBlank(bo.getOrgId()), InfusionRecord::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), InfusionRecord::getRemarks, bo.getRemarks());
        lqw.like(StringUtils.isNotBlank(bo.getDistributionNurseName()), InfusionRecord::getDistributionNurseName, bo.getDistributionNurseName());
        lqw.like(StringUtils.isNotBlank(bo.getPunctureNurseName()), InfusionRecord::getPunctureNurseName, bo.getPunctureNurseName());
        lqw.like(StringUtils.isNotBlank(bo.getPullNeedleNurseName()), InfusionRecord::getPullNeedleNurseName, bo.getPullNeedleNurseName());
        lqw.like(StringUtils.isNotBlank(bo.getOrgName()), InfusionRecord::getOrgName, bo.getOrgName());
        return lqw;
    }

    /**
     * 新增输液室记录
     */
    @Override
    public Boolean insertByBo(InfusionRecordBo bo) {
        InfusionRecord add = BeanUtil.toBean(bo, InfusionRecord.class);
        validEntityBeforeSave(add);
        add.initEntity();
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setInfusionRecordId(add.getInfusionRecordId());
        }
        return flag;
    }

    /**
     * 修改输液室记录
     */
    @Override
    public Boolean updateByBo(InfusionRecordBo bo) {
        InfusionRecord update = BeanUtil.toBean(bo, InfusionRecord.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(InfusionRecord entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除输液室记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }


    /**
     * 批量新增输液室记录
     *
     * @param bo
     * @return
     */
    @Override
    public boolean addInfusionRecordBatch(InfusionItemBo bo) {
        Long l = baseMapper.selectCount(Wrappers.<InfusionRecord>lambdaQuery()
                .eq(InfusionRecord::getItemId, bo.getInfusionItemId())
        );
        List<InfusionRecord> infusionRecordList = new ArrayList<>();
        if (l <= 0) {
            LambdaQueryWrapper<InfusionItem> infusionItemLambdaQueryWrapper = new LambdaQueryWrapper<>();
            infusionItemLambdaQueryWrapper.select(InfusionItem::getInfusionItemId, InfusionItem::getOrgId, InfusionItem::getInfusionNumber);
            String orgName = !sysOrgMap.isEmpty() && StringUtils.isNotBlank(bo.getOrgId())
                    ? sysOrgMap.get(bo.getOrgId()).getOrgName() : "";
            // 同组液体确定同时录入
            infusionItemLambdaQueryWrapper.eq(InfusionItem::getRegisterId, bo.getRegisterId());
            infusionItemLambdaQueryWrapper.eq(InfusionItem::getGroupNumber, bo.getGroupNumber());
            List<InfusionItemVo> infusionItemVos = infusionItemMapper.selectVoList(infusionItemLambdaQueryWrapper);
            for (InfusionItemVo infusionItemVo : infusionItemVos) {
                for (int i = 0; i < infusionItemVo.getInfusionNumber(); i++) {
                    InfusionRecord infusionRecord = new InfusionRecord();
                    infusionRecord.setItemId(infusionItemVo.getInfusionItemId());
                    infusionRecord.setOrgId(infusionItemVo.getOrgId());
                    infusionRecord.setOrgName(orgName);
                    infusionRecord.initEntity();
                    infusionRecord.setInfusionSerialNumber(i);
                    infusionRecordList.add(infusionRecord);
                }
            }
            return baseMapper.insertBatch(infusionRecordList);
        }
        return Boolean.TRUE;
    }


    /**
     * 配液弹出框修改输液室记录
     *
     * @param bo
     * @return
     */
    @Override
    @Transactional
    public boolean updateInfusionRecordByDialog(InfusionRecordBo bo) {
        if (StringUtils.equals(bo.getIsSameGroupCheck(), UserConstants.NO)) {
            updateInfo(bo);
        } else {
            // 通过 登记药品明细获取登记们要拍明细信息
            InfusionItemVo infusionItemVo = infusionItemMapper.selectVoById(bo.getItemId());
            if (ObjectUtil.isNotNull(infusionItemVo)) {
                // 通过 登记药品明细中的登记主表id获取 明细集合
                List<InfusionItemVo> infusionItemVos = infusionItemMapper.selectVoList(Wrappers.<InfusionItem>lambdaQuery()
                        .eq(InfusionItem::getRegisterId, infusionItemVo.getRegisterId())
                );
                // 获取明细id主键 list
                List<String> infusionItemIds = infusionItemVos.stream().map(InfusionItemVo::getInfusionItemId).collect(Collectors.toList());
                // 通过明细id 和 同组液体的每次输液序号 获取符合要求的所有药品输液记录
                List<InfusionRecordVo> infusionRecordVos = baseMapper.selectVoList(Wrappers.<InfusionRecord>lambdaQuery()
                        .eq(InfusionRecord::getInfusionSerialNumber, bo.getInfusionSerialNumber())
                        .in(InfusionRecord::getItemId, infusionItemIds)
                );
                infusionRecordVos.forEach(record -> {
                    InfusionRecordBo recordBo = BeanUtil.toBean(bo, InfusionRecordBo.class);
                    recordBo.setInfusionRecordId(record.getInfusionRecordId());
                    if (CollectionUtils.isNotEmpty(INFUSION_OPERATOR_TYPE_MAP)) {
                        recordBo.setOperatorTypeName(INFUSION_OPERATOR_TYPE_MAP.stream()
                                .filter(i -> StringUtils.equals(recordBo.getOperatorType(), i.getDictValue()))
                                .findAny().get().getDictLabel());
                    }
                    updateInfo(recordBo);
                });
            }
        }
        return Boolean.TRUE;
    }

    @Transactional
    public void updateInfo(InfusionRecordBo bo) {
        // 同组液体是否同时录入 - 否
        baseMapper.update(Wrappers.<InfusionRecord>lambdaUpdate()
                .set(InfusionRecord::getOperatorType, bo.getOperatorType())
                // 配液
                .set(ObjectUtil.isNotNull(bo.getDistributionTime()), InfusionRecord::getDistributionTime, bo.getDistributionTime())
                .set(StringUtils.isNotBlank(bo.getDistributionNurse()), InfusionRecord::getDistributionNurse, bo.getDistributionNurse())
                .set(StringUtils.isNotBlank(bo.getDistributionNurse()), InfusionRecord::getDistributionNurseName,
                        ObjectUtils.isNotEmpty(SYS_USER_MAP) && StringUtils.isNotBlank(bo.getDistributionNurse()) &&
                                ObjectUtils.isNotEmpty(SYS_USER_MAP.get(bo.getDistributionNurse()))?
                                SYS_USER_MAP.get(bo.getDistributionNurse()).getNickName() : "")
                // 穿刺
                .set(ObjectUtil.isNotNull(bo.getPunctureTime()), InfusionRecord::getPunctureTime, bo.getPunctureTime())
                .set(ObjectUtil.isNotNull(bo.getPunctureTime()), InfusionRecord::getInfusionStartTime, bo.getPunctureTime())
                .set(StringUtils.isNotBlank(bo.getPunctureNurse()), InfusionRecord::getPunctureNurse, bo.getPunctureNurse())
                .set(StringUtils.isNotBlank(bo.getPunctureNurse()), InfusionRecord::getPunctureNurseName,
                        ObjectUtils.isNotEmpty(SYS_USER_MAP) && StringUtils.isNotBlank(bo.getPunctureNurse())
                                && ObjectUtils.isNotEmpty(SYS_USER_MAP.get(bo.getPunctureNurse()))?
                                SYS_USER_MAP.get(bo.getPunctureNurse()).getNickName() : "")
                // 换药拔针
                .set(ObjectUtil.isNotNull(bo.getPullNeedleTime()), InfusionRecord::getPullNeedleTime, bo.getPullNeedleTime())
                .set(ObjectUtil.isNotNull(bo.getPullNeedleTime()), InfusionRecord::getInfusionEndTime, bo.getPullNeedleTime())
                .set(StringUtils.isNotBlank(bo.getPullNeedleNurse()), InfusionRecord::getPullNeedleNurse, bo.getPullNeedleNurse())
                .set(StringUtils.isNotBlank(bo.getPullNeedleNurse()), InfusionRecord::getPullNeedleNurseName,
                        ObjectUtils.isNotEmpty(SYS_USER_MAP)&& StringUtils.isNotBlank(bo.getPullNeedleNurse())
                                && ObjectUtils.isNotEmpty(SYS_USER_MAP.get(bo.getPullNeedleNurse()))?
                                SYS_USER_MAP.get(bo.getPullNeedleNurse()).getNickName() : "")
                .eq(InfusionRecord::getInfusionRecordId, bo.getInfusionRecordId())
        );
    }
}
